const axios = require('axios')
const utils = require('./utils')

class MiniProgram {
  constructor(config = {}) {
    this.config = config
    this.axios = this.createAxios()
  }

  createAxios(config = {}) {
    const instance = axios.create({})

    instance.interceptors.request.use(
      (config) => {
        config.onSuccess = (res) => {
          return Promise.resolve(res)
        }

        config.onFail = (error, res) => {
          return Promise.reject([error, res])
        }

        if (config.debug) console.log(config)

        return config
      },
      (error) => {
        return Promise.reject([error])
      }
    )

    instance.interceptors.response.use(
      (response) => {
        const { config } = response

        const { status, data } = response

        if (status && status == 200) {
          if (data.errcode) {
            return config.onFail(data.errmsg, data)
          } else {
            return config.onSuccess(data)
          }
        } else {
          return config.onFail('数据解析异常', data)
        }
      },
      (error) => {
        const { config, response } = error

        if (response) {
          return config.onFail('服务器异常', response.data)
        } else {
          if (config) {
            return config.onFail(error.message, error)
          } else {
            return Promise.reject([error])
          }
        }
      }
    )

    return instance
  }

  /**
   * 获取授权AccessToken
   * https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html#1
   *
   * @param {*} options.code  微信授权传递的Code
   * @param {*} [options.appId]  公众号appId
   * @param {*} [options.secret] 公众号secret
   */
  async getAuthAccessToken(options = {}) {
    const params = {
      appid: options.appId || this.config.appId,
      secret: options.secret || this.config.secret,
      code: options.code,
      grant_type: 'authorization_code',
    }

    utils.ajv(params, {
      required: ['appid', 'secret', 'code', 'grant_type'],
    })

    return this.axios(`https://api.weixin.qq.com/sns/oauth2/access_token`, {
      params,
    })
  }

  /**
   * 获取授权用户信息
   * https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html#3
   *
   * @param {*} options.access_token  微信授权传递的Code
   * @param {*} [options.appId]  公众号appId
   */
  async getAuthUserInfo(options = {}) {
    utils.ajv(options, {
      required: ['access_token', 'openid'],
    })

    return this.axios(`https://api.weixin.qq.com/sns/userinfo`, {
      params: {
        lang: 'zh_CN',
        ...options,
      },
    })
  }

  /**
   * 获取Access token
   * https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
   *
   * @param {*} [options.appId]  公众号appId
   * @param {*} [options.secret] 公众号secret
   */
  async getAccessToken(options = {}) {
    const params = {
      grant_type: 'client_credential',
      appid: options.appId || this.config.appId,
      secret: options.secret || this.config.secret,
    }

    utils.ajv(params, {
      required: ['appid', 'secret', 'grant_type'],
    })

    return this.axios(`https://api.weixin.qq.com/cgi-bin/token`, {
      params,
    })
  }

  /**
   * 获取api_ticket
   * https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#54
   *
   * @param {*} options.accessToken  微信授权传递的Code
   * @param {*} [options.appId]  公众号appId
   * @param {*} [options.secret] 公众号secret
   */
  async gettJsApiTicket(options = {}) {
    utils.ajv(options, {
      required: ['accessToken'],
    })

    options = {
      accessToken: options.accessToken,
      appid: options.appId || this.config.appId,
      secret: options.secret || this.config.secret,
    }

    const params = {
      access_token: options.accessToken,
      type: 'jsapi',
    }

    return this.axios(`https://api.weixin.qq.com/cgi-bin/ticket/getticket`, {
      params,
    })
  }

  /**
   * 获取JSSDK配置
   * https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html
   *
   * @param {String} jsapiTicket  api_ticket
   * @param {String} [options.appId]  公众号appId
   * @param {String} [options.secret] 公众号secret
   */
  async getJsSdkConfig(url, options = {}) {
    options = {
      appid: options.appId || this.config.appId,
      secret: options.secret || this.config.secret,
    }

    const nonceStr = Math.random().toString(36).substr(2, 15)
    const timestamp = parseInt(new Date().getTime() / 1000) + ''
    const signData = {
      jsapi_ticket: options.jsapiTicket,
      noncestr: nonceStr,
      timestamp,
      url: url,
    }

    const signature = utils.jsSdkSign(signData)

    return {
      appId: options.appid, // 必填，公众号的唯一标识
      timestamp, // 必填，生成签名的时间戳
      nonceStr, // 必填，生成签名的随机串
      signature, // 必填，签名
    }
  }
}

module.exports = MiniProgram
